interface RepeatObj {
  repeatName: string;
  repeatCount: number;
}

interface ListStrSetItem {
  repeatName: string;
  repeatCount: number;
  splitStrSet: Array<string>;
}

/**
 * 字符查重
 * @param list 需要查重的字符串数组
 * @param reg 查重中不需要校验的字符正则 例：/,|。|，|“|”|？|；|;|\(|\)|\n|\?/g !!g是必须加的，不然替换不完全
 * @returns {
 *  repeatName: string; 查询的完整字符串 ps: 去除空格和换行之后
 *  repeatCount: number; 重复次数相较于自身的字数的比例
 * }
 * 返回的数组会根据 repeatCount 的大小进行倒序排列
 */
const repeatSearch = function (
  list: Array<string>,
  reg: RegExp | void,
): Array<RepeatObj> {
  const repeatArr: Array<RepeatObj> = [];
  const listStrSet: Array<ListStrSetItem> = [];
  list.forEach((str: string) => {
    const fStr = str.replace(/ |\n/g, '');
    listStrSet.push({
      repeatName: fStr,
      repeatCount: 0,
      splitStrSet: [],
    });
    const listStrSetLast = listStrSet[listStrSet.length - 1];
    const filterStr = reg ? fStr.replace(reg, '') : fStr;
    if (filterStr.length > 5) {
      const tempCodes: Array<string> = [];
      filterStr.split('').forEach((str: string, i) => {
        arrangeKeys(tempCodes, str, i, 5);
      });
      arrangeKeys(tempCodes, 5, true);
      listStrSetLast.splitStrSet.push(...tempCodes);
    }
  });
  for (let i = 0; i < listStrSet.length; i++) {
    const strSetI = listStrSet[i].splitStrSet;
    for (let j = listStrSet.length - 1; j > i; j--) {
      const strSetJ = listStrSet[j].splitStrSet;
      let z = 0;
      for (let x = 0; x < strSetI.length; x++) {
        for (let y = 0; y < strSetJ.length; y++) {
          if (strSetI[x] === strSetJ[y]) {
            z++;
            if (y + 1 >= strSetJ.length || x + 1 >= strSetI.length) {
              z += 4;
            }
          }
        }
      }
      if (z > (strSetJ.length + 4) * 0.7) {
        listStrSet[j].repeatCount += listStrSet[j].repeatName.length;
      }
      if (z > (strSetI.length + 4) * 0.7) {
        listStrSet[i].repeatCount += listStrSet[i].repeatName.length;
      }
    }
    const repeatCount = Math.floor(
      listStrSet[i].repeatCount / listStrSet[i].repeatName.length,
    );

    repeatArr.push({
      repeatName: listStrSet[i].repeatName,
      repeatCount: repeatCount ? repeatCount + 1 : repeatCount,
      // repeatCount: listStrSet[i].repeatCount,
    });
  }
  for (let i = 0; i < repeatArr.length; i++) {
    for (let j = repeatArr.length - 1; j > i; j--) {
      const ra = { ...repeatArr[i] };
      const rj = { ...repeatArr[j] };
      if (ra.repeatCount < rj.repeatCount) {
        repeatArr.splice(i, 1, rj);
        repeatArr.splice(j, 1, ra);
      }
    }
  }

  return repeatArr;
};

/**
 * 字符串重组 例:
 * const str = '12345'
 * const tempCodes2: Array<string> = []
 * const tempCodes3: Array<string> = []
 * str.split('').forEach((str: string, i) => {
 *   arrangeKeys(tempCodes2, str, i, 2);
 *   arrangeKeys(tempCodes3, str, i, 3);
 * });
 * arrangeKeys(tempCodes2, 2, true);
 * arrangeKeys(tempCodes3, 3, true);
 * console.log(tempCodes2) => ['12', '23', '34', '45']
 * console.log(tempCodes3) => ['123', '234', '345']
 * @param tempCodes 存放临时存储循环拆分后的字符串的数组
 * @param key 拆分成单个字符后的字符串
 * @param index 拆分成单个字符后的字符串 索引
 * @param length 需要几个字符为一组
 * @param isEnd 是否循环结束
 */
function arrangeKeys(
  tempCodes: Array<string>,
  key: string | number,
  index: number | boolean,
  length: number | Array<string> | void,
  isEnd: boolean | void,
): void {
  const cloneArguments = {
    cLength: typeof key === 'number' ? key : length,
    cIsEnd: typeof index === 'boolean' ? index : isEnd,
  };
  const { cLength, cIsEnd } = cloneArguments;
  if (typeof cLength !== 'number') return;
  if (cIsEnd) {
    let i = 0;
    tempCodes.some((key: string, index: number): boolean => {
      i = index;
      return key.length < cLength;
    });
    tempCodes.length = i;
    return;
  }
  if (typeof index !== 'number' || typeof key !== 'string') return;
  tempCodes.push(key);
  if (index <= 0) return;
  for (let i = 1; i < cLength; i++) {
    if (index - i < 0) continue;
    if (tempCodes[index - i].length < cLength) {
      tempCodes[index - i] += key;
    }
  }
}

// 在某些字符后面添加换行
function replaceText(text: string, code: string): string {
  let result: string | Array<string> = text;
  result = result.split(code);
  const tabWidth = '';
  result = result.join(`${code}</section><section>${tabWidth}`);
  if (result.indexOf('<section>') !== 0)
    result = '<section>' + tabWidth + result;
  if (!/<\/section>$/.test(result))
    result = /<section>$/.test(result)
      ? result.replace(/<section>$/, '')
      : result + '</section>';

  return result;
}

export { replaceText, repeatSearch, arrangeKeys };
